local GetTime = GetTime;
local FormatTime = AzCastBar.FormatTime;

-- Extra Options
local extraOptions = {
	{
		[0] = "Additional",
		{ type = "Color", var = "colNormal", default = { 0.4, 0.6, 0.8, 1 }, label = "Flight Bar Color" },
	},
};

-- Vars
local b = AzCastBar.CreateBar();
local data;

--------------------------------------------------------------------------------------------------------
--                                           Frame Scripts                                            --
--------------------------------------------------------------------------------------------------------

-- OnUpdate
local function OnUpdate(self,elapsed)
	if (not self.fadeTime) then
		-- Progress
		self.timeProgress = (GetTime() - self.flightStart);
		if (self.entry) then
			self.status:SetValue(self.timeProgress);
			self.time:SetText(FormatTime(FlightTimes_Data[self.entry] - self.timeProgress)..(self.cfg.showTotalTime and " / "..FormatTime(FlightTimes_Data[self.entry]) or ""));
		else
			self.time:SetText(FormatTime(self.timeProgress));
		end
		-- Check if we landed
		if (self.timeProgress > 10) and (not UnitOnTaxi("player")) then
			FlightTimes_Data[self.from.." / "..self.dest] = self.timeProgress;
			self.fadeTime = self.cfg.fadeTime;
		end
	-- FadeOut
	elseif (self.fadeElapsed < self.fadeTime) then
		self.fadeElapsed = (self.fadeElapsed + elapsed);
		self:SetAlpha(1 - self.fadeElapsed / self.fadeTime);
	else
		self:Hide();
	end
end

-- OnEvent -- Cancel Flight if User Accepts Summon or Leaves the World
local function OnEvent(self,event)
	if (self:IsVisible()) and (event == "CONFIRM_SUMMON" or event == "PLAYER_LEAVING_WORLD") then
		self.fadeTime = b.cfg.fadeTime;
		AzMsg("|2FlightTimes|r Flight Timer Aborted, User Summoned or Zoned.");
	end
end

-- Init Bar for Flight
local function StartFlight()
	b.name:SetText(b.dest);
	b.status:SetMinMaxValues(0,b.entry and FlightTimes_Data[b.entry] or 0);
	b.status:SetValue(0);
	b.fadeTime = nil;
	b.fadeElapsed = 0;
	b:SetAlpha(b.cfg.alpha);
	b:Show();
end

--------------------------------------------------------------------------------------------------------
--                                     HOOK: TaxiNodeOnButtonEnter                                    --
--------------------------------------------------------------------------------------------------------
hooksecurefunc("TaxiNodeOnButtonEnter",function(button)
	-- If enabled, Add flight time on all flightpoints except current
	if (b.cfg.enabled) and (TaxiNodeGetType(button:GetID()) ~= "CURRENT") then
		-- Find From and Dest Nodes
		b.from, b.dest = nil, TaxiNodeName(button:GetID());
		for i = 1, NumTaxiNodes() do
			if (TaxiNodeGetType(i) == "CURRENT") then
				b.from = TaxiNodeName(i);
				break;
			end
		end
		-- Continue only if both points are found
		if (b.from and b.dest) then
			b.time1 = FlightTimes_Data[b.from.." / "..b.dest];
			b.time2 = FlightTimes_Data[b.dest.." / "..b.from];
			if (b.time1 or b.time2) then
				if (b.time1) then
					GameTooltip:AddDoubleLine("Flight Time:",FormatTime(b.time1),nil,nil,nil,1,1,1);
				end
				if (b.time2) then
					GameTooltip:AddDoubleLine("Return Flight Time:",FormatTime(b.time2),nil,nil,nil,1,1,1);
				end
			else
				GameTooltip:AddLine("Unknown Flight Time");
			end
			GameTooltip:Show();
		end
	end
end);
--------------------------------------------------------------------------------------------------------
--                                         HOOK: TakeTaxiNode                                         --
--------------------------------------------------------------------------------------------------------
local TakeTaxiNode_Real = TakeTaxiNode;
function TakeTaxiNode(nodeId)
	-- Check if enabled
	if (b.cfg.enabled) and (TaxiNodeGetType(nodeId) ~= "CURRENT") then
		-- Find From and Dest Nodes
		b.from, b.dest = nil, TaxiNodeName(nodeId);
		for i = 1, NumTaxiNodes() do
			if (TaxiNodeGetType(i) == "CURRENT") then
				b.from = TaxiNodeName(i);
				break;
			end
		end
		-- Find Table Entry, but do only so if both points are found
		if (b.from and b.dest) then
			if (FlightTimes_Data[b.from.." / "..b.dest]) then
				b.entry = b.from.." / "..b.dest;
			elseif (FlightTimes_Data[b.dest.." / "..b.from]) then
				b.entry = b.dest.." / "..b.from;
			else
				b.entry = nil;
			end
			-- Init Bar
			b.flightStart = GetTime();
			StartFlight();
		end
	end
	-- Take Taxi
	TakeTaxiNode_Real(nodeId);
end

--------------------------------------------------------------------------------------------------------
--                                              Finalize                                              --
--------------------------------------------------------------------------------------------------------

-- ConfigChanged
function b:OnConfigChanged(cfg,barId)
	if (FlightTimes_MergeTables) then
		FlightTimes_MergeTables();
		data = FlightTimes_Data;
	end

	if (cfg.enabled) then
		self:RegisterEvent("CONFIRM_SUMMON");
		self:RegisterEvent("PLAYER_LEAVING_WORLD");
		self.status:SetStatusBarColor(unpack(cfg.colNormal));
	else
		self:UnregisterAllEvent();
	end
end

-- Init
b.token = "Flight";
b.options = extraOptions;
b.icon:SetTexture("Interface\\Icons\\Ability_Druid_FlightForm");
b:SetPoint("CENTER",0,50);
b:SetScript("OnUpdate",OnUpdate);
b:SetScript("OnEvent",OnEvent);
tinsert(AzCastBar.frames,b);